﻿using System.Diagnostics.Contracts;

namespace DaveSexton.Labs
{
#if NETFX_CORE
	internal sealed class WindowsStoreConsoleLabHost : WindowsStoreConsoleLab
#elif WINDOWS_PHONE
	internal sealed class PhoneConsoleLabHost : PhoneConsoleLab
#elif SILVERLIGHT
	internal sealed class SilverlightConsoleLabHost : SilverlightConsoleLab
#else
	internal sealed class WindowsConsoleLabHost : WindowsConsoleLab
#endif
	{
		#region Public Properties
		public override string SourceCode
		{
			get
			{
				return lab.SourceCode;
			}
		}

		public override string SourceXaml
		{
			get
			{
				return lab.SourceXaml;
			}
		}
		#endregion

		#region Private / Protected
		internal Lab HostedLab
		{
			get
			{
				Contract.Ensures(Contract.Result<Lab>() != null);

				return lab;
			}
		}

		private readonly Lab lab;
		#endregion

		#region Constructors
#if NETFX_CORE
		private WindowsStoreConsoleLabHost(Lab lab)
#elif WINDOWS_PHONE
		private PhoneConsoleLabHost(Lab lab)
#elif SILVERLIGHT
		private SilverlightConsoleLabHost(Lab lab)
#else
		private WindowsConsoleLabHost(Lab lab)
#endif
		{
			Contract.Requires(lab != null);
			Contract.Ensures(!HasProxy);

			this.lab = lab;
		}
		#endregion

		#region Methods
		[ContractInvariantMethod]
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "Required for code contracts.")]
		private void ObjectInvariant()
		{
			Contract.Invariant(lab != null);
		}

		internal static Lab Create(Lab lab)
		{
			Contract.Requires(lab != null);
			Contract.Ensures(Contract.Result<Lab>() != null);
			Contract.Ensures(Contract.Result<Lab>().IsProxy);

#if NETFX_CORE
			var host = new WindowsStoreConsoleLabHost(lab);
#elif WINDOWS_PHONE
			var host = new PhoneConsoleLabHost(lab);
#elif SILVERLIGHT
			var host = new SilverlightConsoleLabHost(lab);
#else
			var host = new WindowsConsoleLabHost(lab);
#endif

			var proxy = new ProxyLab(host);

			Contract.Assume(proxy.IsProxy);

			host.Proxy = proxy;

			Contract.Assume(proxy.IsProxy);

			return proxy;
		}

		public override string FormatSourceCode(string source)
		{
			return lab.FormatSourceCode(source);
		}

		public override string FormatSourceXaml(string source)
		{
			return lab.FormatSourceXaml(source);
		}

		protected override async void Main()
		{
			if (lab.CanExecute())
			{
				await lab.ExecuteAsync();
			}
		}
		#endregion
	}
}